package com.inspectortime.webapp;

import java.util.LinkedHashSet;
import java.util.Set;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import com.inspectortime.domain.Inspection;
import com.inspectortime.domain.InspectorCompany;
import com.inspectortime.domain.pricing.PricingPlanType;
import com.inspectortime.util.SpringValidatorUtils;
import com.mkode.util.java.lang.ClassUtils;

/**
 * Validator for the inspection scheduling form only.
 * 
 */
public class InspectionPropertyInformationValidator implements Validator {
	
	public boolean supports(Class clazz) {
		return ClassUtils.isInstanceOf(clazz, InspectionCriteria.class);
	}

	public void validate(Object obj, Errors errors) {

		// NOTE: Required field validation is handled in an "unusual" way, so be
		// sure to be consistent
		InspectionCriteria inspectionCriteria = (InspectionCriteria) obj;
		validateRequiredFields(inspectionCriteria.getInspection(), inspectionCriteria.getInspectorCompany(), errors);	

		// Add further validations here
		SpringValidatorUtils.rejectIfTooLong(errors, "inspection.property.location.street1", "tooLong", 50);
		SpringValidatorUtils.rejectIfTooLong(errors, "inspection.property.location.city", "tooLong", 50);
		SpringValidatorUtils.rejectInvalidZip(errors, "inspection.property.location.zipCode");		
		
	}

	protected void validateRequiredFields(Inspection inspection, InspectorCompany company, Errors errors) {
		
		Set<String> requiredFields = this.getRequiredFields(company);
		for (String path : requiredFields) {
			ValidationUtils.rejectIfEmptyOrWhitespace(errors, path, "required");
			SpringValidatorUtils.rejectIfZero(errors, path, "required");				
		}
	}

	/**
	 * Gets the string paths of all required fields for an inspection. Public so
	 * that it can be used in template display logic.
	 * 
	 * @param company
	 * @return
	 */
	public Set<String> getRequiredFields(InspectorCompany company) {

		// Use a set to store paths to prevent duplicates (LinkedHashSet preserves ordering)
		Set<String> requiredFields = new LinkedHashSet<String>();

		// Additional "standard" fields to validate (not from price adjusters)
		requiredFields.add("inspection.homeBuyer.name.first");
		requiredFields.add("inspection.homeBuyer.name.last");
		requiredFields.add("inspection.homeBuyer.email");
		requiredFields.add("inspection.homeBuyer.phone");
		requiredFields.add("inspection.property.location.street1");
		requiredFields.add("inspection.property.location.city");
		requiredFields.add("inspection.property.location.state");
		requiredFields.add("inspection.property.location.zipCode");

		// Pricing-plan dependent fields
		if (company.getPricingPlanType() == PricingPlanType.BedsAndBaths) {
			requiredFields.add("inspection.property.numberOfBedrooms");			
			requiredFields.add("inspection.property.numberOfBathrooms");
		} else if (company.getPricingPlanType() == PricingPlanType.ListingPrice) {
			requiredFields.add("inspection.property.listedPrice");			
		}  else if (company.getPricingPlanType() == PricingPlanType.SquareFootage) {
			requiredFields.add("inspection.property.squareFeet");			
		} 		

		return requiredFields;
	}
	
	
	public boolean isRequired(String path, InspectorCompany company) {
		return getRequiredFields(company).contains(path);
	}

}
